package renpyas3.model.structs
{
	import br.com.stimuli.loading.BulkLoader;
	import flash.media.Sound;
	import flash.utils.Dictionary;
	import org.osflash.thunderbolt.Logger;
	import renpyas3.model.AssetsLoader;
	
	/**
	 * a Screen in Renpy is a Flash IDE "scene".  
	 * All the game can be in one screen defined in script.py or alternativelly more 
	 * screens that they invoke with call screen
	 * So there seems to be a one .py file to one screen equivalence.
	 */
	public class RenpyScreen
	{
		private var _vectorOfLines:Vector.<String>;
		private var _path:String;
		private var _labelsLineNumber:Vector.<uint>;
		private var _labelBlocks:Vector.<RenpyLabelBlock>;
		private var _labelBlocksDictionary:/*RenpyLabelBlock*/Dictionary;
		private var _charactersDictionary:/*RenpyCharacter*/Dictionary;
		private var _imagesForThisScreen:/*RenpyImage*/Dictionary;
		private var _soundsForThisScreen:/*Sound*/Dictionary;
		private var _variablesDictionary:/*RenpyImage*/Dictionary;
		private var _assetsLoaderPtr:AssetsLoader;
		
		public function RenpyScreen(vectorOfLines:Vector.<String>, path:String, assetsLoaderPtr:AssetsLoader) 
		{
			_vectorOfLines = vectorOfLines;
			_assetsLoaderPtr = assetsLoaderPtr;
			_path = path;
			_labelsLineNumber = new Vector.<uint>();
			_labelBlocks = new Vector.<RenpyLabelBlock>();
			_labelBlocksDictionary = new Dictionary();
			_imagesForThisScreen = new Dictionary();
			_soundsForThisScreen = new Dictionary();
			_charactersDictionary = new Dictionary();
			_variablesDictionary = new Dictionary();
			
			//trimAllLines();
			parseScreen();
			createLabelBlocks();
		}
		
		
		/**
		 * remove whitespace at the begginning and end
		 * in all lines
		 */
		private function trimAllLines():void
		{
			for (var i:uint = 0; i < _vectorOfLines.length ; i++ )
			{
				_vectorOfLines[i] = f_trim(_vectorOfLines[i]);
			}			
		}
		
		/**
		 * remove whitespace at the begginning and end
		 */
		public static function f_trim(str:String):String
		{
			//remove whitespace
			return(str.replace(/^\s+|\s+$/g, ""));
		}
		
		
		/**
		 * go through all the lines finding the line number for the labels and images
		 */
		private function parseScreen():void
		{
			var firstWord:String;
			var firstSpace:int;
			var currLine:String
			
			//remove whitespace at the begginning and end
			for (var i:uint = 0; i < _vectorOfLines.length ; i++ )
			{
				//Logger.info(s);
				currLine = f_trim(_vectorOfLines[i]);
				firstSpace = currLine.indexOf(" ");
				if (firstSpace != -1)
				{
					firstWord = currLine.substr(0, firstSpace);
					//Logger.info(firstWord);
					parseLine(firstWord, i, currLine);
				}
			}
		}

		/**
		 * process only commands understood by screen
		 */
		private function parseLine(command:String, lineNumber:uint,  currLine:String):void
		{
			switch(command)
			{
				case "label":
					_labelsLineNumber.push(lineNumber);
					break;
				
				case "image":
					var newImage:RenpyImage = new RenpyImage(_vectorOfLines, currLine, lineNumber, _path, _assetsLoaderPtr);
					_imagesForThisScreen[newImage.name] = newImage; //enable search by name
					//_imagesLayer.addChild(newImage.loader);
					break;
					
				case "define":
				case "$":
					parseDefinition(currLine, lineNumber);
					break;
			}
		}

		/**
		 * parse commmands starting with 'define'
		 * for now only Characters
		 */		
		private function parseDefinition(line:String, lineNumber:uint):void
		{
			line = f_trim(line);
			//define s = Character('Sylvie', color="#c8ffc8")
			var defName:String;
			var charName:String = "";
			var charColor:String = "FFFFFF";
			
			var secondWordIndex:int = line.indexOf(" ");
			var equalsSignIndex:int = line.indexOf("=");
			var defTypeIndex:int = line.indexOf("Character(", equalsSignIndex);
			var pauseIndex:int = line.indexOf("renpy.pause(");
			var lastParenthesisIndex:int = line.indexOf(")");
			
			if (secondWordIndex == -1)
			{
				Logger.error("RenpyScreen::parseDefinition ERROR trying to var name in:"+line+" -lineNumber:"+lineNumber);
			}
			if (pauseIndex != -1 && lastParenthesisIndex != -1)
			{
				//is a pause param for the transition
				//handled by labelblock
			}
			else if (equalsSignIndex == -1)
			{
				Logger.error("RenpyScreen::parseDefinition ERROR trying to find = after var name in:"+line+" -lineNumber:"+lineNumber);
			}
			else
			{

				defName = line.substr(secondWordIndex + 1, equalsSignIndex - secondWordIndex - 1);
				defName = f_trim(defName);

				if (defTypeIndex != -1)
				{
					//this is a character
					var charNameStart:int = line.indexOf("'",defTypeIndex);
					var charNameEnd:int = line.indexOf("'",charNameStart+1);
					var colorStart:int = line.indexOf("#", defTypeIndex);
					if (colorStart == -1) 
					{
						//not using # for color
						colorStart = line.indexOf("\"", defTypeIndex);
					}
					
					var colorEnd:int = line.indexOf("\"",colorStart);			
					if (defTypeIndex == -1)
					{
						Logger.error("RenpyScreen::parseDefinition ERROR trying to find definition type (Character) after = in:"+line+" -lineNumber:"+lineNumber);

					}
					else
					{
						if (charNameStart == -1)
						{
							Logger.error("RenpyScreen::parseDefinition ERROR trying to find charNameStart in:"+line+" -lineNumber:"+lineNumber);
						}
						else if (charNameEnd == -1)
						{
							Logger.error("RenpyScreen::parseDefinition ERROR trying to find charNameEnd in:"+line+" -lineNumber:"+lineNumber);
						}
						else
						{
							charName = line.substr(charNameStart + 1, charNameEnd - charNameStart- 1);
							charName = charName.replace("'", ""); //remove quotation marks
							charName = charName.replace("'", ""); //remove last quotation marks
							charName = f_trim(charName);
						}
						
						if (colorStart == -1)
						{
							Logger.error("RenpyScreen::parseDefinition ERROR trying to find colorStart in:"+line+" -lineNumber:"+lineNumber);
						}
						else if (colorEnd == -1)
						{
							Logger.error("RenpyScreen::parseDefinition ERROR trying to find colorEnd in:"+line+" -lineNumber:"+lineNumber);
						}			
						else
						{
							charColor = line.substr(colorStart+1, colorEnd - colorStart- 1);
							charColor = f_trim(charColor);
							
						}
						
						//Logger.info("RenpyScreen::parseDefinition --defName:" + defName+ "---charname:"+charName+"--charColor:"+charColor+"<"); 
						_charactersDictionary[defName] = new RenpyCharacter(charName, charColor);
						
					}
				}
				else
				{
					//is not a character, then it must be a variable
					var varValue:String = line.substr(equalsSignIndex+1);
					varValue = f_trim(varValue);
					var booleanValue:Boolean;
					if (varValue.toLowerCase() == "true")
					{
						booleanValue = true;
					}
					else if (varValue.toLowerCase() == "false")
					{
						booleanValue = false;
					}
					else
					{
						Logger.error("RenpyScreen::parseDefinition ERROR not boolean var value  for defName:"+defName+" in:"+line+" -lineNumber:"+lineNumber);
					}
					
					//if var is not initiallized, asign the first value found
					if (_variablesDictionary[defName] == null)
					{
						_variablesDictionary[defName] = booleanValue
					}
					else
					{
						//the var is already defined, so this line 
						//is an instruction to change value and would be 
						//processed in labelBlock
					
					}
				}
			}
		}
		
		/**
		 * instance all line blocks with the indexes found 
		 * while parsing
		 */
		private function createLabelBlocks():void
		{
			var newBlock:RenpyLabelBlock;
			for (var i:uint = 0; i < _labelsLineNumber.length-1; i++)
			{
				newBlock = new RenpyLabelBlock(_vectorOfLines, _path, _charactersDictionary, _variablesDictionary, _soundsForThisScreen, _labelsLineNumber[i], _labelsLineNumber[i + 1] - 1, _labelBlocks.length+1)
				_labelBlocks.push(newBlock);//for sequencial access, to continue with next block in this list when curr finished playing
				Logger.info("RenpyScreen::createLabelBlocks --newBlock.name:" + newBlock.name + "<");
				_labelBlocksDictionary[newBlock.name] = newBlock; //enable search by name
			}
			//and push last manually
			newBlock = new RenpyLabelBlock(_vectorOfLines, _path, _charactersDictionary, _variablesDictionary, _soundsForThisScreen, _labelsLineNumber[_labelsLineNumber.length - 1], _vectorOfLines.length - 1, -1);
			_labelBlocks.push(newBlock);
			_labelBlocksDictionary[newBlock.name] = newBlock; //enable search by name
			
		}
		
		/**
		 * list of blocks, secuential order
		 */
		public function get labelBlocks():Vector.<RenpyLabelBlock> { return _labelBlocks; }

		/**
		 * to access list of blocks, by label name
		 */
		public function get labelBlocksDictionary():/*RenpyLabelBlock*/Dictionary { return _labelBlocksDictionary; }

		/**
		 * to access list of blocks, by character defName
		 */
		public function get charactersDictionary():/*RenpyCharacter*/Dictionary { return _charactersDictionary; }
		
		/**
		 * to access images by full image name (two words, i.e: "sylvie2 normal" or "sylvie2 giggle")
		 */
		public function get imagesForThisScreen():/*RenpyImage*/Dictionary { return _imagesForThisScreen; }

		/**
		 * to access variables/definitions by name 
		 * (except for character definitions that are in charactersDictionary[])
		 */
		public function get variablesDictionary():Dictionary { return _variablesDictionary; }

		/**
		 * to access sounds by name
		 */
		public function get soundsForThisScreen():/*Sound*/Dictionary { return _soundsForThisScreen; }
	}
}